package educrypt.ciphers.playfair;

import educrypt.commons.Alphabet;

class PlayfairKeyTable {
	private static int COLUMN_SIZE = 5;
	private static int ROW_SIZE = 5;

	private char[][] data;

	public PlayfairKeyTable(String keyword, Alphabet alphabet) {
		data = generateKey(keyword, alphabet);
	}

	private char[][] generateKey(String keyword, Alphabet alphabet) {
		assert alphabet.testBelonging(keyword);

		char[][] data = new char[ROW_SIZE][COLUMN_SIZE];

		Alphabet completeKey = alphabet.getCopyBeginningWith(keyword);
		for (int row = 0; row < ROW_SIZE; row++) {

			for (int column = 0; column < COLUMN_SIZE; column++) {

				int symbolPosition = row * ROW_SIZE + column;
				data[row][column] = completeKey.getSymbolAt(symbolPosition);
			}
		}
		return data;
	}

	public TablePosition getSymbolPosition(char symbol) {
		symbol = Character.toLowerCase(symbol);
		TablePosition symbolPosition = new TablePosition();
		boolean found = false;
		for (int row = 0; row < ROW_SIZE && !found; row++) {
			for (int column = 0; column < COLUMN_SIZE && !found; column++) {
				found = symbol == this.data[row][column];
				if (found) {
					symbolPosition.setPosition(row, column);
				}
			}
		}
		return symbolPosition;
	}

	public TablePosition[] getSymbolsPosition(String symbols) {
		symbols = symbols.toLowerCase();
		TablePosition[] symbolsPosition = new TablePosition[symbols.length()];
		for (int i = 0; i < symbols.length(); i++) {
			symbolsPosition[i] = this.getSymbolPosition(symbols.charAt(i));
		}
		return symbolsPosition;
	}

	public char getSymbolAt(TablePosition position) {
		return data[position.getRow()][position.getColumn()];
	}

	public int getNextPosition(int position) {
		return shiftPosition(position, 1);
	}

	public int getPreviousPosition(int position) {
		return shiftPosition(position, -1);
	}

	private int shiftPosition(int position, int offset) {
		return ((position + offset) % data.length + data.length) % data.length;
	}

	public boolean isValidPosition(TablePosition position) {
		return (position.getRow() >= 0 && position.getRow() < ROW_SIZE)
				|| (position.getColumn() >= 0 && position.getColumn() < COLUMN_SIZE);
	}

	public String toString() {
		String st = "";
		for (char[] row : data) {
			for (char symbol : row) {
				st += symbol + "\t";
			}
			st += "\n";
		}
		return st;
	}
}
